<script setup lang="ts">
import type { FormItemRule } from "naive-ui";
import HelpInfo from "@/components/common/HelpInfo.vue";
import { useLoading } from "@/hooks";
import { Regex } from "@/constants";
import { addMenu, updateMenu } from "@/service/api/menu";
interface Props {
  modalName?: string;
  allRoutes: AppRoute.RowRoute[];
}

const props = withDefaults(defineProps<Props>(), {
  modalName: "",
});

const emit = defineEmits<{
  open: [];
  close: [];
  refresh: [];
}>();

const defaultFormModal: any = {
  parentId: 0,
  menuId: null,
  menuName: null,
  menuType: "M",
  icon: null,
  orderNum: 0,
  isFrame: "1",
  path: null,
  component: null,
  isCache: "0",
  visible: "0",
  status: "0",
  perms: "",
};
const formModel = ref();

type ModalType = "add" | "addP" | "edit";
const modalType = shallowRef<ModalType>("add");
const modalTitle = computed(() => {
  const titleMap: Record<ModalType, string> = {
    add: "添加",
    addP: "添加",
    edit: "编辑",
  };
  return `${titleMap[modalType.value]}${props.modalName}`;
});

const modalVisible = ref(false);
async function openModal(type: ModalType = "add", data: any) {
  emit("open");
  modalType.value = type;
  modalVisible.value = true;
  const handlers = {
    async add() {
      formModel.value = { ...defaultFormModal };
    },
    async addP() {
      formModel.value = { ...defaultFormModal };
      formModel.value.parentId = data.menuId;
    },
    async edit() {
      if (data) formModel.value = { ...data };
    },
  };
  await handlers[type]();
}

const { loading: submitLoading, startLoading, endLoading } = useLoading(false);

function closeModal() {
  modalVisible.value = false;
  endLoading();
  emit("close");
}

defineExpose({
  openModal,
});

const formRef = ref();
async function submitModal() {
  const handlers = {
    async add() {
      return new Promise((resolve) => {
        addMenu(formModel.value).then(()=>{
          window.$message.success("新建成功");
          resolve(true);
          emit("refresh");
        })
        .finally(()=>{
          endLoading()
        })
      });
    },
    async edit() {
      return new Promise((resolve) => {
        updateMenu(formModel.value).then(()=>{
          window.$message.success("编辑成功");
          resolve(true);
          emit("refresh");
        })
        .finally(()=>{
          endLoading()
        })
      });
    },
    async addP() {
      return true;
    },
  };
  await formRef.value?.validate();
  startLoading();
  (await handlers[modalType.value]()) && closeModal();
}

const dirTreeOptions = computed(() => {
  return JSON.parse(JSON.stringify(props.allRoutes));
});

const rules = {
  menuName: {
    required: true,
    message: "请输入菜单名称",
    trigger: "blur",
  },
  path: {
    required: true,
    message: "请输入菜单路径",
    trigger: "blur",
  },
  component: {
    required: true,
    message: "请输入组件路径",
    trigger: "blur",
  },
};
</script>

<template>
  <n-modal
    v-model:show="modalVisible"
    :mask-closable="false"
    preset="card"
    :title="modalTitle"
    class="w-700px"
    :segmented="{
      content: true,
      action: true,
    }"
  >
    <n-form
      ref="formRef"
      :rules="rules"
      label-placement="left"
      :model="formModel"
      label-align="left"
      :label-width="100"
    >
      <n-grid :cols="2" :x-gap="18">
        <n-form-item-grid-item :span="2" path="parentId">
          <template #label>
            父级目录
            <HelpInfo message="不填写则为顶层菜单" />
          </template>
          <n-tree-select
            v-model:value="formModel.parentId"
            filterable
            clearable
            :options="dirTreeOptions"
            key-field="menuId"
            label-field="menuName"
            children-field="children"
            placeholder="请选择父级目录"
          />
        </n-form-item-grid-item>
        <n-form-item-grid-item :span="1" label="菜单类型" path="menuType">
          <n-radio-group v-model:value="formModel.menuType" name="radiogroup">
            <n-space>
              <n-radio value="M"> 目录 </n-radio>
              <n-radio value="C"> 菜单 </n-radio>
              <n-radio value="F"> 按钮 </n-radio>
            </n-space>
          </n-radio-group>
        </n-form-item-grid-item>
        <n-form-item-grid-item :span="1" label="菜单名称" path="menuName">
          <n-input v-model:value="formModel.menuName" placeholder="请输入菜单名称" />
        </n-form-item-grid-item>
        <n-form-item-grid-item
          :span="1"
          label="图标"
          path="icon"
          v-if="formModel.menuType !== 'F'"
        >
          <icon-select v-model:value="formModel.icon" />
        </n-form-item-grid-item>
        <n-form-item-grid-item
          :span="2"
          label="路由路径"
          path="path"
          v-if="formModel.menuType !== 'F'"
        >
          <n-input v-model:value="formModel.path" placeholder="Eg: /system/user" />
        </n-form-item-grid-item>
        <n-form-item-grid-item
          v-if="formModel['meta.menuType'] === 'page'"
          :span="2"
          label="组件路径"
          path="component"
        >
          <n-input
            v-model:value="formModel.component"
            placeholder="Eg: /system/user/index.vue"
          />
        </n-form-item-grid-item>
        <n-form-item-grid-item :span="1" path="orderNum">
          <template #label>
            菜单排序
            <HelpInfo message="数字越小，同级中越靠前" />
          </template>
          <n-input-number v-model:value="formModel.orderNum" />
        </n-form-item-grid-item>
        <n-form-item-grid-item :span="1" path="perms" v-if="formModel.menuType === 'F'">
          <template #label>
            按钮权限
            <HelpInfo message="system:user:list" />
          </template>
          <n-input v-model:value="formModel.perms" />
        </n-form-item-grid-item>
        <n-form-item-grid-item
          v-if="formModel.menuType === 'C'"
          :span="1"
          label="页面缓存"
          path="isCache"
        >
          <n-switch
            v-model:value="formModel.isCache"
            checked-value="0"
            unchecked-value="1"
          />
        </n-form-item-grid-item>
        <n-form-item-grid-item :span="1" label="侧边菜单隐藏" path="visible">
          <n-switch
            v-model:value="formModel.visible"
            checked-value="0"
            unchecked-value="1"
          />
        </n-form-item-grid-item>
        <n-form-item-grid-item :span="1" label="启用状态" path="status">
          <n-switch
            v-model:value="formModel.status"
            checked-value="0"
            unchecked-value="1"
          />
        </n-form-item-grid-item>
      </n-grid>
    </n-form>
    <template #action>
      <n-space justify="center">
        <n-button @click="closeModal"> 取消 </n-button>
        <n-button type="primary" :loading="submitLoading" @click="submitModal">
          提交
        </n-button>
      </n-space>
    </template>
  </n-modal>
</template>

<style scoped></style>
